package com.automannn.cas.practice.casServerCustomWebflow;

import org.springframework.beans.BeansException;
import org.springframework.binding.convert.service.DefaultConversionService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.webflow.config.FlowBuilderServicesBuilder;
import org.springframework.webflow.config.FlowDefinitionRegistryBuilder;
import org.springframework.webflow.conversation.ConversationManager;
import org.springframework.webflow.conversation.impl.SessionBindingConversationManager;
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
import org.springframework.webflow.engine.impl.FlowExecutionImplFactory;
import org.springframework.webflow.execution.repository.impl.DefaultFlowExecutionRepository;
import org.springframework.webflow.execution.repository.snapshot.FlowExecutionSnapshotFactory;
import org.springframework.webflow.execution.repository.snapshot.SimpleFlowExecutionSnapshotFactory;
import org.springframework.webflow.executor.FlowExecutor;
import org.springframework.webflow.executor.FlowExecutorImpl;
import org.springframework.webflow.mvc.builder.MvcViewFactoryCreator;
import org.springframework.webflow.mvc.servlet.FlowHandlerAdapter;
import org.springframework.webflow.mvc.servlet.FlowHandlerMapping;

import java.util.List;

/**
 * @author chenkh
 * @time 2021/12/16 20:24
 */
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@RestController
public class SpringBootCasTest implements ApplicationContextAware {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootCasTest.class);
    }

    private ApplicationContext applicationContext;

    @RequestMapping("hi")
    public String sayHi(){
        return "hello,world!";
    };


    @Bean
    public HandlerMapping loginFlowHandlerMapping(FlowDefinitionRegistry flowDefinitionRegistry) {
        FlowHandlerMapping handler = new FlowHandlerMapping();
        handler.setOrder(2);
        handler.setFlowRegistry(flowDefinitionRegistry);
//        handler.setInterceptors(Collections.EMPTY_LIST);
        return handler;
    }

    @Bean
    public HandlerAdapter flowHandlerAdapter(FlowExecutor executor){
        FlowHandlerAdapter flowHandlerAdapter = new FlowHandlerAdapter();
        flowHandlerAdapter.setFlowExecutor(executor);
        return flowHandlerAdapter;
    }

    @Bean
    public FlowBuilderServices flowBuilderServices(List<ViewResolver> viewResolvers){
        FlowBuilderServicesBuilder flowBuilderServicesBuilder= new FlowBuilderServicesBuilder();
        MvcViewFactoryCreator mvcViewFactoryCreator = new MvcViewFactoryCreator();

        mvcViewFactoryCreator.setViewResolvers(viewResolvers);
        flowBuilderServicesBuilder.setViewFactoryCreator(mvcViewFactoryCreator);
        flowBuilderServicesBuilder.setConversionService(new DefaultConversionService());
        return flowBuilderServicesBuilder.build();
    };

    @Bean
    public FlowDefinitionRegistry flowDefinitionRegistry(FlowBuilderServices flowBuilderServices){
        FlowDefinitionRegistryBuilder builder =new FlowDefinitionRegistryBuilder(this.applicationContext);
        builder.addFlowLocation("classpath:webflow/login/login-webflow.xml","login");
        builder.addFlowLocation("classpath:webflow/logout/logout-webflow.xml","logout");
        builder.setFlowBuilderServices(flowBuilderServices);

        return builder.build();
    };

    @Bean
    public FlowExecutor flowExecutor(FlowDefinitionLocator locator){
        FlowExecutionImplFactory factory = new FlowExecutionImplFactory();

        ConversationManager manager = new SessionBindingConversationManager();
        FlowExecutionSnapshotFactory snapshotFactory = new SimpleFlowExecutionSnapshotFactory(factory,locator);

        DefaultFlowExecutionRepository repository = new DefaultFlowExecutionRepository(manager,snapshotFactory);

        //必须设置key生成器
        factory.setExecutionKeyFactory(repository);

        FlowExecutor flowExecutor=new FlowExecutorImpl(locator,factory,repository);
        return flowExecutor;
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
